#!/bin/bash

# get_interface.sh
#
# 功能：
# 该脚本用于获取本机的物理网络接口名称，避免回环、虚拟和无线接口。
# 它整合了多种方法来检测接口名称，并对结果进行去重处理，确保每个接口只显示一次。
#
# 支持的检测方法包括：
#   1. lshw：使用硬件信息来提取物理接口名称。
#   2. ip route：从路由表中提取默认接口名称。
#   3. sysfs：从系统文件中提取PCI物理接口名称。
#   4. ip -o -4 route：使用IP命令显示默认接口。
#
# 使用方法：
# 直接运行脚本即可，无需参数：
#   ./get_interface.sh
#
# 输出示例：
#   尝试通过多种方法获取网络接口：
#   enp3s0
#   eth0

# 检查接口是否为物理网卡（排除虚拟、回环和无线接口）
function is_physical_interface() {
    local iface=$1
    # 判断接口是否存在于设备目录中，且不是回环或无线接口
    [[ -d "/sys/class/net/$iface/device" ]] && [[ $iface != lo* ]] && [[ ! $iface == *"vpn"* ]] && [[ ! $iface == wlp* ]] && [[ ! $iface == wlan* ]]
}

# 去重函数：过滤重复接口名称
function print_unique() {
    local seen
    for item in "$@"; do
        # 如果接口未被记录，则打印并记录
        if [[ -z ${seen[$item]} ]]; then
            echo "$item"
            seen[$item]=1
        fi
    done
}

# 方法1：使用 lshw 获取接口名称
function get_interface_lshw() {
    # 检查 lshw 命令是否可用
    if command -v lshw &>/dev/null; then
        local iface=$(lshw -class network 2>/dev/null | grep -A 5 "Ethernet interface" | grep name | awk -F': ' '{print $2}')
        # 验证接口是否为物理接口
        if is_physical_interface "$iface"; then
            echo "$iface"
        fi
    fi
}

# 方法2：使用 ip route 获取默认路由接口
function get_interface_ip_route() {
    local iface=$(ip route | grep default | sed -e "s/^.*dev.//" -e "s/.proto.*//")
    # 验证接口是否为物理接口
    if is_physical_interface "$iface"; then
        echo "$iface"
    fi
}

# 方法3：通过 sysfs 获取 PCI 物理接口
function get_interface_sysfs() {
    local iface=$(find /sys/class/net ! -type d | xargs --max-args=1 realpath | awk -F'/' '/pci/{print $NF}')
    # 验证接口是否为物理接口
    if is_physical_interface "$iface"; then
        echo "$iface"
    fi
}

# 方法4：使用 ip -o -4 route 获取默认接口
function get_interface_ip_o() {
    local iface=$(ip -o -4 route show to default | awk '{print $5}')
    # 验证接口是否为物理接口
    if is_physical_interface "$iface"; then
        echo "$iface"
    fi
}

# main 函数：调用所有方法进行测试并去重
function main() {
    echo "尝试通过多种方法获取网络接口："
    local interfaces=()
    interfaces+=("$(get_interface_lshw)")
    interfaces+=("$(get_interface_ip_route)")
    interfaces+=("$(get_interface_sysfs)")
    interfaces+=("$(get_interface_ip_o)")
    # 打印唯一的接口名称
    print_unique "${interfaces[@]}"
}

# 调用主函数
main
